﻿using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using VideoServer.Model;
using VideoServer.ViewModel;
using VideoServer.ViewModel.Helpers;

namespace VideoServer.Helpers
{
    public class UdpState
    {
        public IPEndPoint e { get; set; }
        public UdpClient u { get; set; }
    }
    public class MyUDPServer 
    {
        //一个完整空对地图像数据包长度
        int fullDataLen = 2376;
        //消息类型起始字节序号
        int msgTypeIndex = 4;
        //机组ID起始字节序号
        int groupIdIndex = 6;
        //本机ID起始字节序号
        int myIdIndex = 7;
        //CRC校验起始字节序号
        int crcIndex = 2356;
        private int localPort = 8002;
        private DataParseViewModel dataParseVM = null;
        //线程安全的字典集合
        private ConcurrentDictionary<string, String> videoFileList = null;
        private UdpClient u = null;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="localPort">本地监听端口</param>
        /// <param name="dataVm">数据分析窗口上下文实例</param>
        public MyUDPServer(int localPort,DataParseViewModel dataVm) 
        {
            this.localPort = localPort;
            dataParseVM = dataVm;
            videoFileList = new ConcurrentDictionary<string, string>();
        }

        //数据接收
        private void Receive()
        {
            IPEndPoint e = new IPEndPoint(IPAddress.Any, localPort);
            u = new UdpClient(e);

            UdpState s = new UdpState();
            s.e = e;
            s.u = u;
            u.BeginReceive(new AsyncCallback(OnReceive),s);
        }

        private void OnReceive(IAsyncResult ar)
        {
            UdpState us = (UdpState)ar.AsyncState;
            UdpClient u = us.u;
            IPEndPoint e = us.e;

            byte[] receiveBytes = u.EndReceive(ar, ref e);
            u.BeginReceive(new AsyncCallback(OnReceive), us);
            //数据处理
            ParseReceiveData(receiveBytes);
        }

        //数据处理
        private void ParseReceiveData(byte[] data)
        {
            if (data.Length >= fullDataLen)
            {
                byte groupId = data[groupIdIndex];
                byte myId = data[myIdIndex];
                string tempKey = groupId + "," + myId;
                //为每个ID创建视频存储文件
                if (!videoFileList.Keys.Contains(tempKey))
                {
                    videoFileList.TryAdd(tempKey, SaveVideoFile.CreateFile(tempKey));
                }
                if (CheckCRC(data))
                {
                    //解析完整数据用于界面显示
                    ReceiveData rd = new ReceiveData();
                    object rd1 = rd;
                    ByteStructHelper.ByteArrayToStructureEndian(data, ref rd1, 0);
                    ReceiveData rdata = (ReceiveData)rd1;
                    byte[] status = BitConverter.GetBytes(rdata.deviceStatus);
                    string armSta = null, netSta = null;
                    if ((status[1] & 0x80 >> 7) == 1)
                        armSta = "正常";
                    else
                        armSta = "异常";
                    if ((status[1] & 0x40 >> 6) == 1)
                        netSta = "收到数据";
                    else
                        netSta = "未收到数据";
                    DispatcherHelper.CheckBeginInvokeOnUI(() =>
                    {
                        if (!dataParseVM.Packets.Any(x => x.ID == tempKey))
                        {
                            Packet tempPacket = new Packet()
                            {
                                ID = tempKey,
                                Temperature = rdata.temperature,
                                ArmStatus = armSta,
                                NetStatus = netSta,
                                RemainMem = rdata.remainMemory
                            };
                            dataParseVM.Packets.Add(tempPacket);
                        }
                        else
                        {
                            Packet tempPacket = dataParseVM.Packets.First(x => x.ID == tempKey);
                            tempPacket.Temperature = rdata.temperature;
                            tempPacket.ArmStatus = armSta;
                            tempPacket.NetStatus = netSta;
                            tempPacket.RemainMem = rdata.remainMemory;
                        }
                    });
                }
                //保存视频数据
                byte[] videoBytes = new byte[2300];
                string path = null;
                videoFileList.TryGetValue(tempKey,out path);
                SaveVideoFile.WriteData(videoBytes,path);
            }
        }
        private bool CheckCRC(byte[] fullDataBytes)
        {
            byte[] crcBytes = new byte[2];
            Array.Copy(fullDataBytes, crcIndex, crcBytes, 0, crcBytes.Length);
            crcBytes.Reverse();
            UInt16 ccitt_receive = BitConverter.ToUInt16(crcBytes, 0);
            byte[] countCrcBytes = new byte[crcIndex - 2];
            Array.Copy(fullDataBytes, 2, countCrcBytes, 0, countCrcBytes.Length);
            if (ccitt_receive == CRCHelper.crc16_ccitt(countCrcBytes, countCrcBytes.Length))
            {
                return true;
            }
            return false;
        }

        //启动
        public void StartServer()
        {
            Receive();
        }
        //停止
        public void StopServer()
        {
            u.Close();
        }
    }
}
